package com.jie.scanbarcode

import android.annotation.SuppressLint
import android.graphics.BitmapFactory
import android.graphics.ImageFormat
import android.graphics.Rect
import android.util.Size
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.blankj.utilcode.util.LogUtils
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage

/**
 * 二维码解析
 */
class QRCodeAnalysis(
    private val successListener: (Barcode, Int, Int) -> Unit,
    private val failureListener: (Exception) -> Unit,
    private val completeListener: (() -> Unit)? = null,
    private val viewSize: Size? = null,
    private val analysisRect: Rect? = null,
)
    : ImageAnalysis.Analyzer {

    // 缓存计算好的扫描区域，不用每次都计算
    private var mAnalysisRectTrue : Rect? = null
    // 对第一次做特殊操作
    private var isFirst = true

    @SuppressLint("UnsafeExperimentalUsageError")
    override fun analyze(imageProxy: ImageProxy) {
        if (imageProxy.format == ImageFormat.YUV_420_888) {
            try {
                if (isFirst) {
                    LogUtils.i("imageProxy size(${imageProxy.width}, ${imageProxy.height}, ${imageProxy.imageInfo.rotationDegrees})")
                    isFirst = false
                }
                // 解析整张图片
//                val byteArray = ImageUtil.yuv_420_888toNv21(imageProxy)
//                val inputImage = InputImage.fromByteArray(
//                    byteArray, imageProxy.width, imageProxy.height,
//                    imageProxy.imageInfo.rotationDegrees, InputImage.IMAGE_FORMAT_NV21
//                )
                // 计算屏幕上的扫描区域在图片上对应的区域坐标
                calAnalysisRectTrue(analysisRect, viewSize, imageProxy)
                // 裁剪出扫框区域内的图片
                val jpegByteArray =
                    ImageUtil.yuvImageToJpegByteArray(imageProxy, mAnalysisRectTrue, 100)
                val inputImage = InputImage.fromBitmap(
                    BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.size),
                    imageProxy.imageInfo.rotationDegrees
                )
                // 执行图片解析工作
                BarCodeHelper.process(inputImage, successListener, failureListener,{
                    imageProxy.close()
                    completeListener
                }, null)
            } catch (e : Exception) {
                failureListener.invoke(Exception("图片解析失败：$e"))
            }
        } else {
            failureListener.invoke(Exception("不支持的图片格式：${imageProxy.format}"))
        }
    }

    /**
     * 将屏幕上显示的扫描框转换到获取到的图片上
     */
    private fun calAnalysisRectTrue(analysisRect : Rect?, viewSize: Size?, imageProxy: ImageProxy) {
        analysisRect?.let {
            if (mAnalysisRectTrue == null) {
                LogUtils.i("转换前扫描区域: $analysisRect")
                // 若图片有旋转，需要转换高度和宽度
                val needChange = imageProxy.imageInfo.rotationDegrees == 90
                        || imageProxy.imageInfo.rotationDegrees == 270
                val imageWidth = if (needChange) imageProxy.height else imageProxy.width
                val imageHeight = if (needChange) imageProxy.width else imageProxy.height
                // 先缩放比例和图片一致
                val ratioWidth: Float = 1.0f * imageWidth / (viewSize?.width?:1)
                val ratioHeight: Float = 1.0f * imageHeight / (viewSize?.height?:1)
//                val ratio = max(ratioWidth, ratioHeight)
                val centerX: Float = it.exactCenterX() * ratioWidth
                val centerY: Float = it.exactCenterY() * ratioHeight
                val halfWidth: Float = it.width() / 2f
                val halfHeight: Float = it.height() / 2f
                val newHalfWidth = halfWidth * ratioWidth
                val newHalfHeight = halfHeight * ratioHeight
                LogUtils.i("缩放比例: $ratioWidth $ratioHeight")
                LogUtils.i("缩放中心点: start(${it.exactCenterX()}, ${it.exactCenterY()})")
                LogUtils.i("缩放中心点: end(${centerX}, ${centerY})")
                // 缩放扫描区域，与图片大小一致
//                mAnalysisRectTrue = Rect().apply {
//                    left = (centerX - newHalfWidth).toInt()
//                    right = (centerX + newHalfWidth).toInt()
//                    top = (centerY - newHalfHeight).toInt()
//                    bottom = (centerY + newHalfHeight).toInt()
//                }
                mAnalysisRectTrue = Rect().apply {
                    left = (centerY - newHalfHeight).toInt()
                    right = (centerY + newHalfHeight).toInt()
                    top = (centerX - newHalfWidth).toInt()
                    bottom = (centerX + newHalfWidth).toInt()
                }
                LogUtils.i("缩放后的扫描区域: $mAnalysisRectTrue")
            }
        }
    }

}
